<?php
/**
 * @author renjianhong
 * @date 2021-10-25
 */
namespace Modules\Order\Services\Api;

use App\Models\Area;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
use Modules\Order\Entities\BaseModel;
use Modules\Order\Entities\Order;
use Modules\Order\Entities\Cart;
use Modules\Order\Entities\GoodsCat;
use Modules\Order\Entities\GoodsCats;
use Modules\Order\Entities\Goods;
use Modules\Order\Entities\UserLevel;
use Modules\Order\Entities\OrderDetail;
use Modules\Order\Entities\MallSetting;
use Modules\Order\Entities\Coupon;
use Modules\Order\Entities\UserCoupon;
use Modules\Order\Entities\UserAddress;
use Modules\Order\Entities\PostageRules;
use Modules\Order\Entities\OfferPrice;
use Modules\Order\Entities\TerritorialLimitation;
use Modules\Order\Entities\FreeDeliveryRules;
use Modules\Order\Validate\Api\OrderValidate;
use function Sodium\compare;

class OrderServices extends BaseService
{

    /**
     * @var Request
     */
    private $request;


    /**
     * @var OrderValidate
     */
    private $validate;

    private $store;
    private $integral;
    private $address;
    private $address_id;

    /**
     * @param Request $request
     */
    public function __construct(Request $request, OrderValidate $validates)
    {
        $this->request = $request;
        $this->validate = $validates;
        $this->store = MallSetting::first();
        $this->integral = [
            'forehead' => 0,
            'forehead_integral' => 0,
            'integration' => $this->store->integration
        ];
        
    }

    /**
     * 确认订单
     * @return bool
     * @throws \Exception
     */
    public function confirmOrder()
    {
        
        $param = $this->request->input();
        if(!$this->validate->scene("confirm")->check($param)) throw new \Exception($this->validate->getError());

        $user_id = $this->request->attributes->get('userId');
        if($user_id <= 0) throw new \Exception("用户不存在");
        $this->address_id = $this->request->input('address_id');
        
        $user = $this->getUserInfo($user_id);
        $this->address = $this->getAddressData($user_id);
        
        $mch_list = json_decode($param["mch_list"], true);

        foreach ($mch_list as $i => &$mch) {
            if ($mch['mch_id'] == 0) {
                $mch['name'] = '平台自营';
                $mch['send_type'] = $this->store->send_type;
            } else {
                $_mch = Mch::find($mch['mch_id']);
                if (!$_mch) {
                    unset($mch_list[$i]);
                    continue;
                }
                $mch['name'] = $_mch->name;
            }

            $this->getGoodsList($mch['goods_list'],$user);
            
            if (empty($mch['goods_list'])) {
                throw new \Exception('商品不存在', 1);
            }
            $total_price = 0;
            $level_price = 0;
            $integral = [
                'forehead' => 0,
                'forehead_integral' => 0
            ];
            $mch['plugin_type'] = 0;
            foreach ($mch['goods_list'] as $_goods) {
                $total_price += doubleval($_goods['price']);
                $level_price += doubleval($_goods['level_price']);
                $integral['forehead'] += doubleval($_goods['resIntegral']['forehead']);
                $integral['forehead_integral'] += doubleval($_goods['resIntegral']['forehead_integral']);
                if (isset($_goods['bargain_order_id'])) {
                    $mch['plugin_type'] = 2;
                }
            }
            
            $mch['total_price'] = sprintf('%.2f', $total_price);
            $mch['level_price'] = sprintf('%.2f', $level_price);
            $mch['integral'] = $integral;
            
            //获取优惠券列表
            $this->getCouponList($mch,$user);
            
            //获取运费
            $mch['express_price'] = $this->getExpressPrice($mch);
            
            //获取起送规则
            $mch['offer_rule'] = $this->getOfferRule($mch);
           
            //获取限制购买区域规则
            $mch['is_area'] = $this->getTerritorialLimitation($mch);
        }
        
        $data = [
            "pay_type_list" => $this->getPayment(), // 支付方式列表
            "address" => $this->address, // 默认收货地址
            "level" => $this->getUserLevel($user->user_level_id),
            "mch_list" => $mch_list,
            "integral" => $this->integral,
        ];

        return $data;   
    }

    /**
     * 获取商品信息
     * @return
     */
    protected function getGoodsList(&$goods_list,$user)
    {
        
        $goodsIds = [];
        foreach ($goods_list as $i => &$item) {
            if (isset($item['cart_id'])) {
                $cart = Cart::where(['id' => $item['cart_id'],'is_delete' => 0])->first();
                if (!$cart) {
                    unset($goods_list[$i]);
                    continue;
                }
                $item['num'] = $cart->num;
                $attr_id_list = json_decode($cart->attr,true);
                $goods = Goods::find($cart->goods_id);
            } elseif (isset($item['goods_id'])) {
                $attr_id_list = [];
                foreach ($item['attr'] as $_a) {
                    array_push($attr_id_list, $_a['attr_id']);
                }
                $goods = Goods::find($item['goods_id']);
            } else {
                unset($goods_list[$i]);
                continue;
            }
            if (!$goods) {
                unset($goods_list[$i]);
                continue;
            }
            //判断是否超出限购数量
            if(($goods->ucquota && $goods->ucquota > 0)){
                $goodsNum = Goods::getBuyNum($user, $goods->id);
                if ($goodsNum) {

                }else{
                    $goodsNum = 0;
                }
                $goodsTotalNum = intval($goodsNum + $item['num']);
                if ($goodsTotalNum > $goods->ucquota) {
                    throw new \Exception('商品：' . $goods->name . ' 超出购买数量', 1);
                }
            }
            $attr_info = $goods->getAttrInfo($attr_id_list,$goods);
            
            if ($item['num'] > $attr_info['num']) { //库存不足
                unset($goods_list[$i]);
                continue;
            }
            
            $attr_list = DB::table('goods_attr')
                ->whereIn('goods_attr.id', $attr_id_list)
                ->leftJoin('goods_attr_group', 'goods_attr_group.id','=','goods_attr.goods_attr_group_id')
                ->select('goods_attr_group.id AS attr_group_id','goods_attr_group.name as attr_group_name','goods_attr.id AS attr_id','goods_attr.name as attr_name')
                ->get()->toArray();
            
            $item['attr_list'] = $attr_list;
            $item['goods_id'] = $goods->id;
            $item['goods_name'] = $goods->name;
            $domain = BaseModel::getDomain();
            $item['goods_pic'] = $domain.'/'.$goods->pic;
            
            $item['price'] = sprintf('%.2f', ($attr_info['price'] * $item['num']));
            $item['single_price'] = sprintf('%.2f', $attr_info['price']);
            
            $item['weight'] = $goods->weight;
            $item['integral'] = $goods->integral ? $goods->integral : 0;
            $item['freight'] = $goods->freight;
            $item['num_full'] = $goods->num_full;
            $item['price_full'] = $goods->price_full;
            $cat = GoodsCats::where('goods_id',$goods->id)->orderByDesc('created_at')->first();
            $item['goods_cat_id'] = $cat->cat_id;
            $item['id'] = $goods->id;
            
            $level = $this->getLevelData($user->user_level_id);
            
            if ($goods->is_level == 1 && $level && $level->discount < 10) {
                $item['level_price'] = sprintf('%.2f', ($item['price'] * floatval($level->discount) / 10));
                $item['is_level'] = 1;
            } else {
                $item['level_price'] = $item['price'];
                $item['is_level'] = 0;
            }
            
            $integralArr = $this->getIntegralArr((object)$item, $this->store->integral, $goodsIds,$user);
            $item['give'] = $integralArr['give'];
            $item['resIntegral'] = $integralArr['resIntegral'];
            $goodsIds[] = $goods->id;
        }
    }

    /**
     * 获取用户等级信息
     * @param $level
     * @return 
     */
    protected function getLevelData($level)
    {
        $level = UserLevel::where('id',$level)->whereNull('deleted_at')->select('name', 'id', 'discount')
            ->first();
        return $level;
    }

    /**
     * 获取指定分类ID
     * @param $goods_list
     * @return
     */
    protected function getCatIdList(&$goods_list)
    {
        $cat_id_list = [];
        foreach ($goods_list as &$goods) {
            if($goods['goods_cat_id'] == 0){
                $goods_cat_list = GoodsCats::select('cat_id')->where('goods_id', $goods['goods_id'])->get();
                foreach ($goods_cat_list as $goods_cat) {
                    $cat_id_list[] = $goods_cat->cat_id;
                    $goods['cat_id'][] = $goods_cat->cat_id;
                }
            }else{
                $cat_id_list[] = $goods['goods_cat_id'];
                $goods['cat_id'][] = $goods['goods_cat_id'];
            }
            
            $cat_parent_list = GoodsCat::select('parent_id')
                ->whereIn('id',$goods['cat_id'])->where('parent_id', '>', 0)
                ->whereNull('deleted_at')->get()->toArray();
            $cat_id_list = array_merge($cat_parent_list, $cat_id_list);
            $goods['cat_id'] = array_merge($cat_parent_list, $goods['cat_id']);
        }
        unset($goods);
        return array_unique($cat_id_list);
    }

    /**
     * 获取指定商品ID
     * @param $goods_list
     * @return
     */
    protected function getGoodsIdList($goods_list)
    {
        $goods_id_list = [];
        foreach ($goods_list as $goods) {
            $goods_id_list[] = $goods['goods_id'];
        }
        return $goods_id_list;
    }
    
    /**
     * 根据地址ID获取地址
     */
    protected function getAddress($user_id)
    {
        
        if ($this->address_id) {
            $this->address = UserAddress::where([['address_id','=',$this->address_id],['is_delete','=','2']])->first();
        } else {
            $this->address = UserAddress::where([
                ['user_id','=',$user_id],
                ['is_default','=','1'],
                ['is_delete','=','2'],
            ])->first();
            
        }
        
        return $this->address;
    }

    /**
     * 获取收货地址，有address_id优先获取，没有则获取默认地址
     * @return
     */
    protected function getAddressData($user_id)
    {
        $address = $this->getAddress($user_id);
        
        if ($address) {
            return [
                'id' => $address->address_id,
                'name' => $address->name,
                'mobile' => $address->phone,
                'province_id' => $address->province_id,
                'province' => $address->province,
                'city_id' => $address->city_id,
                'city' => $address->city,
                'district_id' => $address->region_id,
                'district' => $address->region,
                'detail' => $address->detail,
                'is_default' => $address->is_default,
            ];
        } else {
            return null;
        }
    }

    /**
     * 积分计算
     * @param $goods_item object 重新编写的goods_item
     * @param $store_integral int 商城设置的积分规则
     * @param $goods_id array 已设置积分的商品id数组
     * @return array
     */
    protected function getIntegralArr($goods_item, $store_integral, $goods_id = array(),$user)
    {
        $integral = json_decode($goods_item->integral, true);
        
        $resIntegral = [
            'forehead' => 0,
            'forehead_integral' => 0,
        ];
        if ($integral) {
            //赠送积分计算
            $give = $integral['give'];
            
            if (strpos($give, '%') !== false) {
                // 百分比
                $give = trim($give, '%');
                $goods_item->give = (int)($goods_item->price * ($give / 100));
            } else {
                // 固定积分
                $goods_item->give = (int)($give * $goods_item->num);
            }
            //抵扣积分计算
            $forehead = $integral['forehead'];
            if ($forehead) {
                if (strpos($forehead, '%') !== false) {//百分比积分抵扣计算

                    if ($forehead >= 100) {
                        $forehead = 100;
                    }
                    if ($integral['more'] == '1') {//多件累计计算
                        $resIntegral['forehead_integral'] = (int)(($forehead / 100) * $goods_item->price * $store_integral);
                    } else {
                        if (!in_array($goods_item->id, $goods_id)) { //不允许多件累计   同id商品值计算一次积分抵扣
                            $resIntegral['forehead_integral'] = (int)(($forehead / 100) * $goods_item->single_price * $store_integral);
                        }
                    }
                } else {

                    if ($integral['more'] == '1') {
                        $resIntegral['forehead_integral'] = (int)($store_integral * $goods_item->price);
                        if ($goods_item->price > ($forehead * $goods_item->num)) {
                            $resIntegral['forehead_integral'] = (int)($forehead * $goods_item->num * $store_integral);
                        }
                    } else {
                        if (!in_array($goods_item->id, $goods_id)) {
                            $goodsPrice = $goods_item->single_price;
                            $resIntegral['forehead_integral'] = (int)($store_integral * $goodsPrice);
                            if ($goodsPrice > $forehead) {
                                $resIntegral['forehead_integral'] = (int)($forehead * $store_integral);
                            }
                        }
                    }
                }
            }
            
            if($this->integral['forehead_integral'] < $user->integral){
                $resetIntegral = $user->integral - $this->integral['forehead_integral'];
                $resIntegral['forehead_integral'] = $resIntegral['forehead_integral'] >= $resetIntegral ? $resetIntegral : $resIntegral['forehead_integral'];
                $resIntegral['forehead'] = sprintf("%.2f", ($resIntegral['forehead_integral'] / $store_integral));
                $this->integral['forehead_integral'] += $resIntegral['forehead_integral'];
                $this->integral['forehead'] += $resIntegral['forehead'];
            }else{
                $resIntegral['forehead_integral'] = 0;
                $resIntegral['forehead'] = 0;
            }
        }

        return [
            'resIntegral' => $resIntegral,
            'give' => $goods_item->give
        ];
    }

    /**
     * 获取优惠券列表
     * @param $mch
     * @return 
     */
    protected function getCouponList(&$mch,$user)
    {
        if ($mch['mch_id'] != 0) {
            $mch['coupon_list'] = [];
            return;
        }
        $goods_total_price = $mch['total_price'];
        $cat_ids = $this->getCatIdList($mch['goods_list']);
        
        $coupon_goods_id = $this->getGoodsIdList($mch['goods_list']);
        
        $where = [
            ['user_coupon.deleted_at','=',null],
            ['user_coupon.is_use' ,'=', 0],
            ['user_coupon.is_expire' ,'=', 0],
            ['user_coupon.user_id' ,'=', $user->id],
            ['coupon.min_price','<=', $goods_total_price],
        ];
        $list = UserCoupon::leftJoin('coupon', 'user_coupon.coupon_id','=','coupon.id')
            ->where($where)
            ->select('user_coupon.user_coupon_id','coupon.reduce_price','coupon.coupon_type','coupon.discount','coupon.min_price','user_coupon.start_time','user_coupon.end_time','user_coupon.apply_range','user_coupon.apply_range_config','user_coupon.get_way','user_coupon.is_use','user_coupon.is_expire')
            ->get()->toArray();
        $events = [
            0 => '平台发放',
            1 => '分享红包',
            2 => '购物返券',
            3 => '领券中心',
        ];
        $new_list = [];
        
        foreach ($list as $i => $item) {
            
            if ($item['start_time'] > (strtotime(date('Y-M-d')) + 86400) || $item['end_time'] < time()) {
                // TODO 优惠券过期
                continue;
            }
            $list[$i]['status'] = 0;
            if ($item['is_use']) {
                $list[$i]['status'] = 1;
            }
            
            if ($item['is_expire']) {
                $list[$i]['status'] = 2;
            }
            
            $list[$i]['min_price_desc'] = $item['min_price'] == 0 ? '无门槛' : '满' . $item['min_price'] . '元可用';
            $list[$i]['start_time'] = date('Y.m.d H:i', $item['start_time']);
            $list[$i]['end_time'] = date('Y.m.d H:i', $item['end_time']);
            
            $list[$i]['event_desc'] = $events[$item['get_way']];
            $list[$i]['min_price'] = doubleval($item['min_price']);
            if($item['coupon_type'] == 2){
                $list[$i]['discount'] = $item['discount'];
            }else{
                $list[$i]['sub_price'] = doubleval($item['reduce_price']);
            }
            
            if ($list[$i]['apply_range'] == 3) {//指定类别
                $list[$i]['cat_id_list'] = json_decode($list[$i]['cat_id_list']);
                if ($list[$i]['cat_id_list'] != null) {
                    if (!array_intersect($list[$i]['cat_id_list'], $cat_ids)) {
                        unset($list[$i]);
                        continue;
                    }
                }
            }elseif ($list[$i]['apply_range'] == 2) {//指定商品
                $list[$i]['apply_range_config'] = json_decode($list[$i]['apply_range_config']);
                if ($list[$i]['apply_range_config'] != null) {
                    if (!array_intersect($list[$i]['apply_range_config'], $coupon_goods_id)) {
                        unset($list[$i]);
                        continue;
                    }
                }
            }
            
            $new_list[] = $list[$i];
        }
        
        $mch['coupon_list'] = $new_list;
    }

    /**
     * 计算运费
     * @param $mch
     * @return
     */
    protected function getExpressPrice($mch)
    {
        $expressPrice = 0;
        
        if ($this->address) {
            $address = $this->address;
            //先计算单品满件包邮和满额包邮
            $resGoodsList = Goods::cutFull($mch['goods_list']);
            
            //再通过运费规则计算运费
            $expressPrice = PostageRules::getExpressPriceMore($address['city_id'], $resGoodsList, $address['province_id']);
        }
        
        //获取包邮规则
        $expressPrice = $this->getFreeDeliveryRules($mch, $expressPrice);
        
        return $expressPrice;
    }

    /**
     * 获取起送规则
     * @return
     */
    protected function getOfferRule($mch)
    {
        $res = [
            'is_allowed' => 0,
            'total_price' => 0,
            'msg' => ''
        ];
        if ($mch['mch_id'] > 0) {
            $res['msg'] = '商户不支持起送规则';
            return $res;
        }
        if (!$this->address) {
            $res['msg'] = '请选择收货地址';
            return $res;
        }
        $offerRule = OfferPrice::first();
        if (!$offerRule) {
            $res['msg'] = '起送规则不存在';
            return $res;
        }
        if ($offerRule->is_enable == 0) {
            $res['msg'] = '起送规则未开启';
            return $res;
        }

        $ruleList = $offerRule->detail;

        $res['total_price'] = $offerRule->total_price;
        if (is_array($ruleList)) {
            foreach ($ruleList as $value) {
                foreach ($value['province_list'] as $item) {
                    if ($item['id'] == $this->address['city_id']) {
                        $res['total_price'] = $value['price'];
                    }
                }
            }
        }

        if ($mch['total_price'] >= $res['total_price']) {
            $res['is_allowed'] = 0;
        } else {
            $res['is_allowed'] = 1;
        }
        $value = round($res['total_price'] - $mch['total_price'], 2);
        $res['msg'] = "自营商品，还差{$value}元起送";

        return $res;
    }

    /**
     * 获取限制购买规则
     * @return
     */
    protected function getTerritorialLimitation($mch)
    {
        $isArea = 0;
        if ($mch['mch_id'] > 0) {
            return $isArea;
        }
        
        if ($this->address) {
            $area = TerritorialLimitation::where([
                ['is_delete','=',0],
                ['is_enable','=',1],
            ])->first();
            
            if ($area) {
                $city_id = []; //限制的地区ID
                $detail = json_decode($area->detail);
                if (!is_array($detail)) {
                    $detail = [];
                }
                foreach ($detail as $key => $value) {
                    foreach ($value->province_list as $key2 => $value2) {
                        $city_id[] = $value2->id;
                    }
                }
                $addressArr = [
                    $this->address['province_id'],
                    $this->address['city_id'],
                    $this->address['district_id']
                ];
                
                $addressArray = array_intersect($addressArr, $city_id);
                
                if (!empty($addressArray)) {
                    $isArea = 1;//不可以购买
                }
            }
        }
        
        return $isArea;
    }
    
    /**
     * 包邮规则
     * @return
     */ 
    protected function getFreeDeliveryRules($mch, $expressPrice)
    {
        if ($expressPrice == 0 && $mch['mch_id'] > 0) {
            return $expressPrice;
        }
        $free = FreeDeliveryRules::where('is_delete',0)->get()->toArray();
        
        foreach ($free as $k => $v) {
            $city = json_decode($v['city'], true);
            foreach ($city as $v1) {
                if (isset($this->address['city_id']) == $v1['id'] && $mch['total_price'] >= $v['price']) {
                    $expressPrice = 0;
                    break;
                }
            }
        }
        
        return $expressPrice;
    }


}